﻿using Koala.Pro.Helpers;
using System.IO;

namespace Koala.Pro.Common
{
    public static class ParameterCheckExtensions
    {
        private static void Require<TException>(bool assertion, string message) where TException : Exception
        {
            if (assertion)
            {
                return;
            }
            if (string.IsNullOrEmpty(message))
            {
                throw new ArgumentNullException("message");
            }
            throw (TException)Activator.CreateInstance(typeof(TException), message);
        }

        public static void Required<T>(this T value, Func<T, bool> assertionFunc, string message)
        {
            if (assertionFunc == null)
            {
                throw new ArgumentNullException("assertionFunc");
            }
            Require<Exception>(assertionFunc(value), message);
        }

        public static void Required<T, TException>(this T value, Func<T, bool> assertionFunc, string message) where TException : Exception
        {
            if (assertionFunc == null)
            {
                throw new ArgumentNullException("assertionFunc");
            }
            Require<TException>(assertionFunc(value), message);
        }

        public static void CheckNotNull<T>(this T value, string paramName) where T : class
        {
            string @string = JsonLanguage.Default.GetString("参数“{0}”不能为空引用。");
            Require<ArgumentNullException>(value != null, string.Format(@string, paramName));
        }

        public static void CheckNotNullOrEmpty(this string value, string paramName)
        {
            CheckNotNull(value, paramName);
            string @string = JsonLanguage.Default.GetString("参数“{0}”不能为空引用或空字符串。");
            Require<ArgumentException>(value.Length > 0, string.Format(@string, paramName));
        }

        public static void CheckNotEmpty(this Guid value, string paramName)
        {
            string @string = JsonLanguage.Default.GetString("参数“{0}”的值不能为Guid.Empty");
            Require<ArgumentException>(value != Guid.Empty, string.Format(@string, paramName));
        }

        public static void CheckNotNullOrEmpty<T>(this IEnumerable<T> collection, string paramName)
        {
            CheckNotNull(collection, paramName);
            string @string = JsonLanguage.Default.GetString("参数“{0}”不能为空引用或空集合。");
            Require<ArgumentException>(collection.Any(), string.Format(@string, paramName));
        }

        public static void CheckLessThan<T>(this T value, string paramName, T target, bool canEqual = false) where T : IComparable<T>
        {
            bool assertion = (canEqual ? (value.CompareTo(target) <= 0) : (value.CompareTo(target) < 0));
            string @string = JsonLanguage.Default.GetString("参数“{0}”的值必须小于或等于“{1}”。");
            string string2 = JsonLanguage.Default.GetString("参数“{0}”的值必须大于“{1}”。");
            string format = (canEqual ? @string : string2);
            Require<ArgumentOutOfRangeException>(assertion, string.Format(format, paramName, target));
        }

        public static void CheckGreaterThan<T>(this T value, string paramName, T target, bool canEqual = false) where T : IComparable<T>
        {
            bool assertion = (canEqual ? (value.CompareTo(target) >= 0) : (value.CompareTo(target) > 0));
            string @string = JsonLanguage.Default.GetString("参数“{0}”的值必须大于或等于“{1}”。");
            string string2 = JsonLanguage.Default.GetString("参数“{0}”的值必须大于“{1}”。");
            string format = (canEqual ? @string : string2);
            Require<ArgumentOutOfRangeException>(assertion, string.Format(format, paramName, target));
        }

        public static void CheckBetween<T>(this T value, string paramName, T start, T end, bool startEqual = false, bool endEqual = false) where T : IComparable<T>
        {
            bool assertion = (startEqual ? (value.CompareTo(start) >= 0) : (value.CompareTo(start) > 0));
            string @string = JsonLanguage.Default.GetString("参数“{0}”的值必须在“{1}”与“{2}”之间。");
            string string2 = JsonLanguage.Default.GetString("参数“{0}”的值必须在“{1}”与“{2}”之间，且不能等于“{3}”。");
            string message = (startEqual ? string.Format(@string, paramName, start, end) : string.Format(string2, paramName, start, end, start));
            Require<ArgumentOutOfRangeException>(assertion, message);
            assertion = (endEqual ? (value.CompareTo(end) <= 0) : (value.CompareTo(end) < 0));
            message = (endEqual ? string.Format(@string, paramName, start, end) : string.Format(string2, paramName, start, end, end));
            Require<ArgumentOutOfRangeException>(assertion, message);
        }

        public static void CheckDirectoryExists(this string directory, string paramName = null)
        {
            CheckNotNull(directory, paramName);
            string @string = JsonLanguage.Default.GetString("指定的目录路径“{0}”不存在。");
            Require<DirectoryNotFoundException>(Directory.Exists(directory), string.Format(@string, directory));
        }

        public static void CheckFileExists(this string filename, string paramName = null)
        {
            CheckNotNull(filename, paramName);
            string @string = JsonLanguage.Default.GetString("指定的文件路径“{0}”不存在。");
            Require<FileNotFoundException>(File.Exists(filename), string.Format(@string, filename));
        }
    }

}
